1. Field of the Invention
The present invention relates to the field of integrated circuits and, more particularly, to testing and verification of integrated circuit designs.
2. Description of the Related Art
Modern integrated circuits (ICs) are developed through the use of hardware description languages (HDLs). HDLs such as VERILOG, VHDL, and the like allow developers to create software-based representations of circuit designs. One advantage of using an HDL is the potential for code reuse from one design to another. This concept has been realized with the commercial availability of intellectual property (IP) cores. In general, an IP core refers to a software representation of a semiconductor, or a portion of a semiconductor, that provides a processing function.
Before HDL logic is made available for commercial use, it must be thoroughly tested and verified. The HDL logic must be tested to ensure that it functions properly and as expected, particularly as defined in the design specification. Typically, this testing is performed using a testbench. A testbench is a verification environment that is comprised of HDL descriptions. These HDL descriptions specify and verify the behavior of a device under test (DUT), in this case HDL logic such as one or more IP cores. In general, the testbench provides a pre-determined input sequence to the DUT and observes the response, or output from the DUT. Generating a testbench involves describing the connections, events, and test vectors for different combinations of transactions involving the DUT.
FIG. 1 is a schematic diagram illustrating an exemplary multithreaded testbench configuration. The testbench can include a generator 105, a driver 110, a monitor 115, and a scoreboard 120, each being implemented as a software module or component. Typically, the testbench is multithreaded in nature, with each of the aforementioned software components operating in a different thread of execution. These components interact with a DUT 125 to perform testing and/or verification.
In terms of functionality, the generator 105 randomly constructs data units to be provided to the DUT 125. The driver 110 can transmit the constructed data units to the DUT 125. The monitor 115 receives processed data units as output from the DUT 125, while the scoreboard 120 examines the output units to determine whether the DUT 125 behaved correctly.
In order to adequately test HDL logic, a series of different test cases are needed. Each test case is directed to testing a particular functionality of the HDL logic. Each test case includes a sequence of user specified commands. The testbench executes these commands, thereby causing particular inputs to be provided to the DUT 125.
FIG. 2 is a block diagram illustrating one technique for implementing a multithreaded testbench configuration. FIG. 2 further illustrates one manner of communication among the multiple threads of a testbench such as the one depicted in FIG. 1. As shown, the testbench configuration includes a master thread 205, a generator thread 210, and other threads 215 of the testbench. The master thread 205 represents a user specified test case. The generator thread 210 corresponds to a test case specific generator module. The other threads 215 are representative of the other modules of the testbench, such as the monitor, driver, and scoreboard, that may interact with a given DUT described.
The generator thread 210 and other threads 215 can be coded in an object oriented style such that each thread requires only a trigger input from the master thread 205 to begin executing. The master thread 205 initializes the generator thread 210 and the other threads 215. The master thread 205 then registers the commands of the user specified test case with the generator thread 210. The generator thread 210 begins executing the commands and the master thread 205 waits for each thread to complete.
One disadvantage of this technique is that a significant amount of time is required for testbench development. For each different test case to be executed, different testbench modules must be coded. Such is the case with the generator module executing in the generator thread 210, particularly as it is complex in nature. The master thread 205, by comparison, is less complex, but still must be recoded for each test case. Developing different sets of testbench modules for each test case significantly increases the amount of time needed for testing.
FIG. 3 is block diagram illustrating another technique for implementing a multithreaded testbench involving the use of semaphores. Semaphores establish which of a plurality of different threads is permitted access to shared data at any given time. This prevents more than one thread from trying to access the same data at the same time, resulting in a fault condition referred to as a collision. As shown, the inter-thread communications are more complex than those illustrated in FIG. 2. A higher degree of handshaking is required between the master thread 305 and the generator thread 310.
Semaphores are particularly useful when randomization is introduced into the testing process. Randomization is used to vary the input vectors that are applied to the DUT. Not only is the content of the input vectors varied, but the length of the input vectors also can be randomized. Accordingly, rather then sending data packets having a constant size, for example 1 KB, data packets between 10 bytes and 4 KB may be provided to the DUT. Randomization facilitates better functional coverage by a test case with less effort on the part of the test engineer. When using randomization, the number of vectors and the time needed to transmit each vector cannot be predicted with any degree of accuracy. Determining when a next command is to be executed, therefore, is difficult. The use of semaphores between the master thread 305 and the generator thread 310 ensures that the generator thread 310 obtains a new command whenever it finishes execution of the previous command.
While this strategy for sharing common data does prevent collisions between threads, it also requires a significant amount of overhead. The handshaking that is needed to implement semaphores within a testbench environment requires both time and processing power. While one thread establishes a lock to write to the shared data, other threads execute in wait loops or are otherwise blocked from accessing the shared data until the owner thread releases the lock. Throughout the time a thread is blocked from executing, processing cycles are consumed as the blocked thread continues to check whether access to the shared data is available.
It would be beneficial to provide a technique for communication within a multithreaded testbench that overcomes the limitations described above.